const { tokenSetting } = require('../../setting')
const { v4: uuidv4 } = require('uuid')
const { aesDecrypt, aesEncrypt } = require('../cipher')
const { getCache, setCache, removeCache } = require('../cache')
const Resp = require('./tokenResp')

const SUCCESS = 0,
  FAIL = -1,
  ERROR = -2,
  UNAUTHORIZED = -401

function encryptToken(userKey, uuid) {
  if (!userKey) {
    return {
      code: FAIL,
      msg: 'UserKey不能为空',
    }
  }
  if (!uuid) {
    // 重新生成uuid
    uuid = uuidv4()
  }
  const tokenStr = `${userKey}.${uuid}`
  token = aesEncrypt(tokenStr, tokenSetting.Key, tokenSetting.Iv)
  return Resp.success({
    userKey,
    uuid,
    token,
  })
}

function decryptToken(token) {
  if (!token) {
    return Resp.fail('token为空')
  }
  tokenStr = aesDecrypt(token, tokenSetting.Key, tokenSetting.Iv)
  tokenArr = tokenStr.split('.')
  if (tokenArr.length < 2) {
    return Resp.error('token长度错误')
  }
  return Resp.success({
    userKey: tokenArr[0],
    uuid: tokenArr[1],
  })
}

// 生成token
function genToken(userKey, data, uuid) {
  const token = encryptToken(userKey, uuid)
  // 加密错误，返回
  if (token.isFail() || token.isError()) {
    return token
  }
  const cacheKey = `${tokenSetting.CacheKey}:${userKey}`
  const userCache = {
    userKey: userKey,
    uuid: token.data.uuid,
    data,
    createTime: Date.now(),
    refreshTime: Date.now() + tokenSetting.MaxRefresh,
  }
  setCache(cacheKey, userCache, tokenSetting.Timeout / 1000)
  return Resp.success(token.data.token)
}

//  验证Token并返回缓存数据
async function validToken(token) {
  if (!token) {
    return Resp.fail('token不能为空')
  }
  // 解密token字符串
  const decryptTokenStr = decryptToken(token)
  if (decryptTokenStr.isSuccess()) {
    // 获取缓存内token信息并返回
    const userData = await getCacheToken(decryptTokenStr.data.userKey)
    if (decryptTokenStr.data.uuid != userData.data.uuid) {
      return Resp.unauthorized('token已过期')
    }
    return userData
  }
  return decryptTokenStr
}

// 获取缓存里的token数据
async function getCacheToken(userKey) {
  const cacheKey = `${tokenSetting.CacheKey}:${userKey}`
  const userCache = await getCache(cacheKey)
  if (userCache) {
    const now = Date.now()
    const refreshTime = userCache.refreshTime
    // 如果当前时间大于刷新时间，则刷新token
    if (now > refreshTime) {
      userCache.createTime = now
      userCache.refreshTime = now + tokenSetting.MaxRefresh
      setCache(cacheKey, userCache, tokenSetting.Timeout / 1000)
    }
    return Resp.success(userCache)
  }
  return Resp.unauthorized()
}

// 删除token
function removeToken(token) {
  // 解密token字符串
  const decryptTokenStr = decryptToken(token)
  if (decryptTokenStr.isSuccess()) {
    const cacheKey = `${tokenSetting.CacheKey}:${decryptTokenStr.data.userKey}`
    removeCache(cacheKey)
    return Resp.success()
  }
  return decryptTokenStr
}

async function getTokenDataByUserKey(userKey) {
  const cacheKey = `${tokenSetting.CacheKey}:${userKey}`
  return await getCache(cacheKey)
}

module.exports = {
  genToken,
  validToken,
  removeToken,
  getTokenDataByUserKey,
}
